
package com.joysuch.wwyt.core.service.impl;

import com.joysuch.wwyt.bp.entity.BpEnterpriseInfo;
import com.joysuch.wwyt.core.common.security.CredentialsDigest;
import com.joysuch.wwyt.core.common.security.Digests;
import com.joysuch.wwyt.core.common.util.Encodes;
import com.joysuch.wwyt.core.entity.BaseLoginAccount;
import com.joysuch.wwyt.core.entity.BaseUser;
import com.joysuch.wwyt.core.entity.dsl.QBaseLoginAccount;
import com.joysuch.wwyt.core.enums.LoginUserStates;
import com.joysuch.wwyt.core.repository.BaseLoginAccountDao;
import com.joysuch.wwyt.core.repository.BaseUserDao;
import com.joysuch.wwyt.core.service.BaseLoginAccountService;
import com.joysuch.wwyt.core.service.BaseUserService;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.util.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
@Slf4j
public class BaseLoginAccountServiceImpl implements BaseLoginAccountService {

    private static final int SALT_SIZE = 8;

    private BaseLoginAccountDao dao;
    private CredentialsDigest credentialsDigest;
    @Autowired
    private BaseUserDao userDao;
    @Autowired
    private BaseUserService baseUserService;

    @Autowired
    public void setDao(BaseLoginAccountDao dao) {
        this.dao = dao;
    }

    public BaseLoginAccountDao getBaseLoginAccountDao() {
        return dao;
    }

    public CredentialsDigest getCredentialsDigest() {
        return credentialsDigest;
    }

    @Autowired
    public void setCredentialsDigest(CredentialsDigest credentialsDigest) {
        this.credentialsDigest = credentialsDigest;
    }

    @Override
    public String save(BaseLoginAccount bean) throws Exception {
        Boolean hasAccount = getUser(bean.getBaseUser().getId());
        if (!hasAccount) {
            BaseLoginAccount account = dao.findFirstByUserName(bean.getUserName());
            if (account != null && account.getBaseUser() != null) {
                throw new IllegalArgumentException("用户名已经存在，是" + account.getBaseUser().getRealName() + "的关联账号");
            } else if (account != null) {
                // 账号存在但是无主
                bean = account;
            }
            BaseUser one = userDao.getOne(bean.getBaseUser().getId());
            entryptPassword(bean);
            bean.setBaseUser(one);
            Long id = bean.getId();
            if (id == null) {
                bean.setFirstLogin(1);
                bean.setLoginHistory(0);
            }
            BaseLoginAccount save = dao.save(bean);
            return "添加成功";
        } else {
            return "已有账户";
        }
    }

    @Override
    public String edit(BaseLoginAccount account) {
        String password = account.getPassword();
        //Assert.isTrue(PasswordCheckUtil.check(password), "密码格式不对，请重新填写");
        Assert.isTrue(password != null && password.length() >= 6 && password.length() <= 32, "密码格式不对，请重新填写");
        BaseLoginAccount loginAccount = dao.findByBaseUser(account.getBaseUser());
        Assert.isTrue(dao.countOfUserNameExcludeId(account.getUserName(), loginAccount.getId()) == 0, "账号已经存在");
        loginAccount.setPassword(account.getPassword());
        entryptPassword(loginAccount);
        loginAccount.setUserName(account.getUserName());
        //密码修改成功，设置非第一次登录
        Integer loginHistory = loginAccount.getLoginHistory();
        if (loginHistory != null && loginHistory == 1) {
            loginAccount.setFirstLogin(0);
        }
        BaseLoginAccount save = dao.save(loginAccount);
        return null;
    }

    private Boolean getUser(Long user) {
        QBaseLoginAccount baseLoginAccount = QBaseLoginAccount.baseLoginAccount;
        Predicate predicate = baseLoginAccount.isNotNull();
        predicate = user == null ? predicate : ExpressionUtils.and(predicate, baseLoginAccount.baseUser.id.eq(user));
        Iterable<BaseLoginAccount> all = dao.findAll(predicate);
        for (BaseLoginAccount loginAccount : all) {
            return true;
        }
        return false;
    }

    private void entryptPassword(BaseLoginAccount bean) {
        byte[] saltBytes = Digests.generateSalt(SALT_SIZE);
        String salt = Encodes.encodeHex(saltBytes);
        bean.setSalt(salt);
        String rawPass = bean.getPassword();
        String encPass = credentialsDigest.digest(rawPass, saltBytes);
        bean.setPassword(encPass);
    }

    @Override
    public BaseLoginAccount findById(Long id) {
        QBaseLoginAccount baseLoginAccount = QBaseLoginAccount.baseLoginAccount;
        Predicate predicate1 = baseLoginAccount.isNotNull();
        predicate1 = id == null ? predicate1 : ExpressionUtils.and(predicate1, baseLoginAccount.baseUser.id.eq(id));
        Iterable<BaseLoginAccount> als = dao.findAll(predicate1);
        for (BaseLoginAccount al : als) {
            BaseLoginAccount a = dao.findById(al.getId());
            return a;
        }

        return null;

    }

    @Override
    public String findAccountNameById(Long id) {
        if (id == null) {
            return "";
        }
        BaseLoginAccount account = findById(id);
        return account == null ? "" : account.getUserName();
    }

    @Override
    public BaseLoginAccount createLoginAccountIfNotExists(Long baseUserId, String userName, String password) {
        BaseUser one = userDao.getOne(baseUserId);
        return createLoginAccountIfNotExists(one, userName, password);
    }

    /*
     * @Override
     * public BaseLoginAccount username(BaseLoginAccount bean) {
     *
     *
     * }
     */

    private String entryptPasswords(BaseLoginAccount bean) {
        byte[] saltBytes = Digests.generateSalt(SALT_SIZE);
        String salt = Encodes.encodeHex(saltBytes);
        bean.setSalt(salt);
        String rawPass = bean.getPassword();
        String encPass = credentialsDigest.digest(rawPass, saltBytes);
        bean.setPassword(encPass);
        return encPass;
    }

    @Override
    public BaseLoginAccount createLoginAccountIfNotExists(BaseUser user, String userName, String password) {
        BaseLoginAccount account = dao.findByBaseUser(user);
        if (account == null) {
            BaseLoginAccount bean = new BaseLoginAccount();
            bean.setUserName(userName);
            bean.setPassword(password);
            bean.setState(LoginUserStates.NORMAL.getCode());
            entryptPassword(bean);
            bean.setBaseUser(user);
            return dao.save(bean);
        }
        return account;
    }

    // @Override
    public BaseLoginAccount addOrUpdateLoginAccount(BaseUser user, String userName, String password) {
        BaseLoginAccount exits = dao.findFirstByUserName(userName);
        Assert.isTrue(exits == null || exits.getBaseUser().getId().equals(user.getId()),
                String.format("登录账号[%s]已被分配给用户[%s]", userName, user.getRealName()));
        BaseLoginAccount account = exits != null ? exits : dao.findByBaseUser(user);
        if (account == null) {
            BaseLoginAccount bean = new BaseLoginAccount();
            bean.setUserName(userName);
            bean.setPassword(password);
            bean.setState(LoginUserStates.NORMAL.getCode());
            entryptPassword(bean);
            bean.setBaseUser(user);
            return dao.save(bean);
        } else {
            account.setUserName(userName);
            dao.save(account);
        }
        return account;
    }

    public BaseLoginAccount addOrUpdateLoginAccountV2(BaseUser user, String userName, String password, BpEnterpriseInfo info) {
        BaseLoginAccount exits = dao.findFirstByUserNameAndCurrentCompany(userName, info.getOrgCode(), info.getTenentId());
        Assert.isTrue(exits == null || exits.getBaseUser().getId().equals(user.getId()),
                String.format("登录账号[%s]已被分配给用户[%s]", userName, user.getRealName()));
        BaseLoginAccount account = exits != null ? exits : dao.findByBaseUser(user);
        if (account == null) {
            BaseLoginAccount bean = new BaseLoginAccount();
            bean.setUserName(userName);
            bean.setPassword(password);
            bean.setState(LoginUserStates.NORMAL.getCode());
            bean.setOrgCode(info.getOrgCode());
            bean.setTenentId(info.getTenentId());
            entryptPassword(bean);
            bean.setBaseUser(user);
            return dao.save(bean);
        } else {
            account.setOrgCode(info.getOrgCode());
            account.setTenentId(info.getTenentId());
            account.setUserName(userName);
            dao.save(account);
        }
        return account;
    }

    /**
     * 开启/关闭账户
     *
     * @param userId
     * @param showState
     * @return
     */
    @Override
    public void setLoginAccount(Long userId, Integer showState) {
        if (showState == null || (!showState.equals(0) && !showState.equals(1))) {
            log.info("账号开启/关闭:userId{" + userId + "},deleteFlag传值{" + showState + "}不正确");
            throw new IllegalArgumentException("系统繁忙请稍后重试");
        }
        String str = baseUserService.username(userId);
        if (StringUtils.isBlank(str) || str.equals("未有账户")) {
            throw new IllegalArgumentException("请先设置账户");
        }
        dao.setAccountStateByUserId(showState, userId);
    }
}
